package com.cqie.hospitalescort.service.login;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cqie.hospitalescort.DTO.AuthUser;
import com.cqie.hospitalescort.DTO.WeiXinSessionInfoDTO;
import com.cqie.hospitalescort.VO.LoginVO;
import com.cqie.hospitalescort.aspect.WxUserRegister;
import com.cqie.hospitalescort.config.utils.JwtUtil;
import com.cqie.hospitalescort.controller.params.LoginParam;
import com.cqie.hospitalescort.controller.params.RegisterParam;
import com.cqie.hospitalescort.controller.params.WxUserDetailParam;
import com.cqie.hospitalescort.entity.AdminUser;
import com.cqie.hospitalescort.enums.RoleEnum;
import com.cqie.hospitalescort.exception.BusinessException;
import com.cqie.hospitalescort.mapper.AdminUserMapper;
import com.cqie.hospitalescort.service.weixin.WeiXinService;
import com.cqie.hospitalescort.utils.Asserts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.Objects;

@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    @Autowired
    private AdminUserMapper adminUserMapper;
    @Autowired
    private WeiXinService weiXinService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 微信登录
     *
     * @param param
     * @return
     */
    @Override
    @WxUserRegister
    @Transactional
    public LoginVO login(LoginParam param, WeiXinSessionInfoDTO sessionInfo) {

        UsernamePasswordAuthenticationToken authenticationToken;
        if (Objects.nonNull(sessionInfo)) {
            authenticationToken = new UsernamePasswordAuthenticationToken(sessionInfo.getOpenId(), "");
        } else {
            authenticationToken = new UsernamePasswordAuthenticationToken(param.getUsername(), param.getPassword());
        }

        LoginVO loginVO = new LoginVO();
        try {
            Authentication authenticate = authenticationManager.authenticate(authenticationToken);
            if (authenticate.isAuthenticated()) {
                AuthUser user = (AuthUser) authenticate.getPrincipal();
                BeanUtils.copyProperties(user, loginVO);

                String token;
                if (Objects.nonNull(sessionInfo)) {
                    token = JwtUtil.createToken(sessionInfo.getOpenId(), RoleEnum.getRoleName(user.getRole()),"WeiXinUser");
                } else {
                    token = JwtUtil.createToken(param.getUsername(), RoleEnum.getRoleName(user.getRole()), user.getPassword());
                }

                loginVO.setToken("Bearer " + token);
                return loginVO;
            } else {
                throw new BusinessException("账密错误！");
            }
        } catch (Exception e) {
            throw new BadCredentialsException(e.getMessage());
        }
    }

    /**
     * 管理员注册
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterParam param) {
        AdminUser adminUser = adminUserMapper.selectOne(new LambdaQueryWrapper<AdminUser>().eq(AdminUser::getUsername, param.getUsername()));
        if (Objects.nonNull(adminUser)) {
            throw new BusinessException("用户名已存在");
        }
        adminUser = new AdminUser();
        String encodePassword = passwordEncoder.encode(param.getPassword());
        adminUser.setPassword(encodePassword);
        adminUser.setUsername(param.getUsername());
        adminUser.setRole(RoleEnum.ADMIN.getRole());
        adminUserMapper.insert(adminUser);
    }


}
